using System;
using System.Diagnostics.Contracts;
using Autofac;
using NHibernate;
using NHibernate.Cfg;
using NhJump.Persistence.Context;
using NhJump.Persistence.Wcf.Autofac.Repositories;

namespace NhJump.Persistence.Wcf.Autofac.IoC
{
    public class NHibernateComponentModule : Module
    {
        private readonly string _connectionStringName;
        private readonly Type _serviceType;

        public NHibernateComponentModule(string connectionStringName, Type serviceType = null)
        {
            _connectionStringName = connectionStringName;
            _serviceType = serviceType;
        }

        protected override void Load(ContainerBuilder builder)
        {
            Contract.Assert(builder != null, "Builder container is null");
            Contract.Assert(_connectionStringName != null, "Connection String Name is null");

            INHibernateConfigProvider configProvider = new NHibernateConfigProvider(_connectionStringName);
            var cfg = configProvider.GetConfiguration();

            if (_serviceType != null)
            {
                UnitOfWorkFactory.Register(_serviceType, configProvider);
            }

            builder.RegisterInstance(cfg).As<Configuration>().SingleInstance();
            builder.RegisterInstance(BuildSessionFactory(cfg)).As<ISessionFactory>().SingleInstance();
            builder.Register(x => UnitOfWorkBinder.CurrentUnitOfWork ?? new UnitOfWork(x.Resolve<ISessionFactory>()))
                .As<IUnitOfWork>();
            builder.RegisterAssemblyTypes(typeof (CustomerRepository).Assembly)
                .AsImplementedInterfaces();
        }

        private static ISessionFactory BuildSessionFactory(Configuration config)
        {
            var sessionFactory = config.BuildSessionFactory();

            if (sessionFactory == null)
                throw new Exception("Cannot build NHibernate Session Factory");

            return sessionFactory;
        }
    }
}